/**
 * Copyright 2021 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.modulelink.util;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 重写策略
 * 
 * @author jianggujin
 *
 */
public class JOverideStrategy {
    /**
     * java的包必须排除，避免安全隐患
     */
    public static final String[] DEFAULT_EXCLUDED_PACKAGES = new String[] { "java.*", "javax.*", "sun.*", "oracle.*",
            "com.jianggujin.modulelink.*" };

    /**
     * 需要排除的包
     */
    private final Set<String> excludedPackages = new HashSet<String>();

    public JOverideStrategy() {
        this.excludedPackages.addAll(new HashSet<String>(Arrays.asList(DEFAULT_EXCLUDED_PACKAGES)));
    }

    /**
     * 判断该名字是否是需要覆盖的class
     *
     * @param className 类名
     * @return 需要覆盖则返回true
     */
    public boolean isEligibleForOverriding(String className) {
        JAssert.checkNotNull(className, "className must not be null");
        if (!isExcluded(className)) {
            return true;
        }
        return false;
    }

    /**
     * 判断该名字是否是需要覆盖的资源
     *
     * @param name 资源名称
     * @return 需要覆盖则返回true
     */
    public boolean isResourceEligibleForOverriding(final String name) {
        JAssert.checkNotNull(name, "name must not be null");
        if (!isExcluded(name.replace("/", "."))) {
            return true;
        }
        return false;
    }

    /**
     * 判断class是否排除
     *
     * @param name 类名
     * @return 需要排除则返回true
     */
    protected boolean isExcluded(String name) {
        for (String packageName : this.excludedPackages) {
            if (packageName.endsWith("*")) {
                if (name.startsWith(packageName.substring(0, packageName.length() - 1))) {
                    return true;
                }
            } else {
                int index = name.lastIndexOf('.');
                if (index > 0 && packageName.equals(name.substring(0, index))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 添加需要排除的包
     * 
     * @param packageName 包名
     */
    public void addExcludedPackage(String packageName) {
        JAssert.checkNotNull(packageName, "packageName must not be null");
        this.excludedPackages.add(packageName);
    }

    /**
     * 添加需要排除的包
     * 
     * @param packageNames 包名
     */
    public void addExcludedPackages(Collection<String> packageNames) {
        JAssert.checkNotNull(packageNames, "packageNames must not be null");
        this.excludedPackages.addAll(packageNames);
    }

    public Set<String> getExcludedPackages() {
        return excludedPackages;
    }
}
